/** 事件派发 */
class EventsDispatch {
    protected eventSet: any = {};
    protected tmpEventSet: any = {};
    /** 添加事件监听 */
    public on(eventName: string, method: Function, scope: object = this): void {
        if (this.eventSet[eventName] == null) {
            this.eventSet[eventName] = [];
        }
        this.eventSet[eventName].push({ fn: method, scope: scope });
    };
    /**
     * 添加事件监听到第一个
     * @param eventName 
     * @param method 
     * @param scope 
     */
    public unshift(eventName: string, method: Function, scope: object = this): void {
        if (this.eventSet[eventName] == null) {
            this.eventSet[eventName] = [];
        }
        this.eventSet[eventName].unshift({ fn: method, scope: scope });
    };
    /** 注销事件监听 */
    public off(eventName: string, method?: Function, scope: object = this): void {
        let list = eventName.split(" ");
        list.forEach(s => {
            if (this.eventSet[s] === undefined)
                return;
            if (method === undefined) {
                // delete this.eventSet[s];
                return;
            }
            for (let f in this.eventSet[s]) {
                if (this.eventSet[s][f].fn === method && this.eventSet[s][f].scope === scope) {
                    this.eventSet[s].splice(f, 1);
                    break;
                }
            }
            if (this.eventSet[s].length === 0)
                delete this.eventSet[s];
        });
    }
    /** 临时执行 */
    public tmpOn(eventName: string, method: Function, scope: object) {
        if (this.eventSet[eventName] !== undefined) {
            this.tmpEventSet[eventName] = this.eventSet[eventName];
            this.eventSet[eventName] = [];
        }
        this.on(eventName, method, scope);
    }
    /** 临时执行注销 */
    public tmpOff(eventName: string) {
        this.off(eventName);
        if (this.tmpEventSet[eventName] !== undefined) {
            this.eventSet[eventName] = this.tmpEventSet[eventName];
            delete this.tmpEventSet[eventName];
        }
    }
    /** 只执行一次 */
    public once(eventName: string, method: Function, scope: object): void {
        if (this.eventSet[eventName] === undefined) {
            this.eventSet[eventName] = [];
        }
        let me = this;
        let fn = (args: any) => {
            me.off(eventName, fn, scope);
            method.call(scope, args);
        };
        this.eventSet[eventName].push({ fn: fn, scope: scope });
    }
    /** 执行多次 */
    public timesExcute(eventName: string, method: Function, scope: object, times: number): void {
        if (this.eventSet[eventName] === undefined) {
            this.eventSet[eventName] = [];
        }
        let me = this;
        let count = 0;
        let fn = (args: any) => {
            count++;
            if (count === times)
                me.off(eventName, fn, scope);
            method.call(scope, args);
        };
        this.eventSet[eventName].push({ fn: fn, scope: scope });
    }

    /** 注销所有事件 */
    public offAllEvents(): void {
        this.eventSet = {};
    };
    /** 判断是否包含 */
    public containsKey(eventName: string): boolean {
        return this.eventSet[eventName] != null;
    }
    /** 触发事件 */
    public fireEvent(eventName: string, ...args: any[]): boolean {
        // if (eventName != 'EarthRenderer')
        //     console.log(eventName)
        let isOk = true;
        if (!this.eventSet || this.eventSet[eventName] == null)
            return isOk;
        let list = this.eventSet[eventName];
        try {
            for (let i = 0; i < list.length; i++) {
                if (list[i].fn.apply(list[i].scope, args)) {
                    isOk = false;
                    // break;
                }
            }
        } catch (err) {
            console.error(err);
        }
        return isOk;
    }

    /**
     * 监听属性变化
     * @param propertyName 要监听变化的属性
     * @param listener getter&setter
     */
    public addPropertyListener(propertyName, listener: { getter: Function, setter: Function }) {
        const _this = this;
        if (Array.isArray(propertyName)) {
            for (let i = 0; i < propertyName.length; i++) {
                let prop = propertyName[i];
                _this[`_${prop}`] = _this[prop]
                Object.defineProperty(_this, prop, {
                    get: function () {
                        return listener.getter ? listener.getter(propertyName[i]) : _this[`_${prop}`];
                    },
                    set: function (newValue) {
                        _this[`_${prop}`] = newValue
                        if (listener.setter)
                            listener.setter(propertyName[i], newValue)
                    }
                })
            }
        }
        else {
            _this[`_${propertyName}`] = _this[propertyName]
            Object.defineProperty(_this, propertyName, {
                get: function () {
                    return listener.getter ? listener.getter(propertyName) : _this[`_${propertyName}`];
                },
                set: function (newValue) {
                    _this[`_${propertyName}`] = newValue
                    if (listener.setter)
                        listener.setter(newValue)
                }
            })
        }
    }
}
export { EventsDispatch }